﻿using Aliyun.Acs.Core.Exceptions;
using Aop.Api;
using Aop.Api.Domain;
using Aop.Api.Request;
using Aop.Api.Response;
using Aop.Api.Util;
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace AVIS.OutBound.OrderPay
{
    /// <summary>
    ///  订单支付服务
    /// </summary>
    public class OrderPayLogService : IOrderPayLogService
    {

        private readonly IOrderPayLogManager _orderPayLogManager;
        private readonly IOrderPayTransManager _orderPayTransManager;
        private readonly IPayGatewayLogManager _payGatewayLogManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        public OrderPayLogService(IOrderPayLogManager orderPayLogManager, IOrderPayTransManager orderPayTransManager, IPayGatewayLogManager payGatewayLogManager)
        {
            _orderPayLogManager = orderPayLogManager;
            _orderPayTransManager = orderPayTransManager;
            _payGatewayLogManager = payGatewayLogManager;
        }

        /// <summary>
        /// 订单支付
        /// </summary>
        /// <param name="type">支付方式(ALIPAY支付宝、WECHATPAY微信支付)</param>
        /// <param name="orderNo">商户订单号</param>
        /// <param name="subject">商品名称</param>
        /// <param name="amount">金额（元）</param>
        public void Pay(string type, string orderNo, string subject, string amount)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            if (type == "ALIPAY")
            {
                AliPay(orderNo, subject, amount);
            }
            else if (type == "WECHATPAY")
            {
                Dictionary<String, Object> dic = new Dictionary<string, object>();
                dic.Add("msg","调用微信支付成功！");
                System.Web.HttpContext.Current.Response.Write(jss.Serialize(dic));
            }
            else
            {
                System.Web.HttpContext.Current.Response.Write("请选择支付方式！");
            }
        }

        /// <summary>
        /// 支付宝支付
        /// </summary>
        /// <param name="orderNo">商户订单号</param>
        /// <param name="subject">商品名称</param>
        /// <param name="amount">金额（元）</param>
        public void AliPay(string orderNo, string subject, string amount)
        {
            DefaultAopClient client = new DefaultAopClient(config.gatewayUrl, config.app_id, config.private_key, "json", "1.0", config.sign_type, config.alipay_public_key, config.charset, false);
            //外部订单号，商户网站订单系统中唯一的订单号
            string out_trade_no = orderNo.Trim();

            //付款金额
            string total_amout = amount.Trim();

            //商品描述
            string body = subject;

            //支付中途退出返回商户网站地址
            string quit_url = "";

            //组装业务参数model
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.Body = body;
            model.Subject = subject;
            model.TotalAmount = total_amout;
            model.OutTradeNo = out_trade_no;
            model.ProductCode = "QUICK_WAP_WAY";
            model.QuitUrl = quit_url;

            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
            //设置支付完成同步回调地址
            //request.SetReturnUrl("");

            //设置支付完成异步通知接收地址
            //request.SetNotifyUrl("");

            //将业务model载入到request
            request.SetBizModel(model);
            AlipayTradeWapPayResponse response = null;
            try
            {
                response = client.pageExecute(request, null, "post");
                string form = response.Body;
                System.Web.HttpContext.Current.Response.Write(form);

                //保存预支付（开始调用支付宝）
                savePay(1);
            }
            catch (ServerException exp)
            {
                throw exp;
            }
            catch (ClientException exp)
            {
                throw exp;
            }
        }

        /// <summary>
        /// 支付宝支付回调
        /// </summary>
        public void CbAliPay(){
            /* 实际验证过程建议商户添加以下校验。
            1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
            */
            JavaScriptSerializer jss = new JavaScriptSerializer();
            Dictionary<string, string> sArray = GetRequestPost();
            if (sArray.Count != 0){
                bool flag = AlipaySignature.RSACheckV1(sArray, config.alipay_public_key, config.charset, config.sign_type, false);
                if (flag){
                    //交易状态
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理，不执行商户的业务程序

                    //注意：
                    //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                    string trade_status = System.Web.HttpContext.Current.Request.Form["trade_status"];
                    string trade_no = System.Web.HttpContext.Current.Request.Form["trade_no"];//交易号
                    string out_trade_no = System.Web.HttpContext.Current.Request.Form["out_trade_no"];//商户订单号
                    
                    saveCbPay(1, out_trade_no, trade_no, trade_status, jss.Serialize(sArray));
                    System.Web.HttpContext.Current.Response.Write("success");
                }else{
                    System.Web.HttpContext.Current.Response.Write("fail");
                }
            }
        }

        /// <summary>
        /// 获取返回参数
        /// </summary>
        public Dictionary<string, string> GetRequestPost(){
            int i = 0;
            Dictionary<string, string> sArray = new Dictionary<string, string>();
            System.Collections.Specialized.NameValueCollection coll;
            coll = System.Web.HttpContext.Current.Request.Form;
            String[] requestItem = coll.AllKeys;
            for (i = 0; i < requestItem.Length; i++){
                sArray.Add(requestItem[i], System.Web.HttpContext.Current.Request.Form[requestItem[i]]);
            }
            return sArray;
        }

        private void savePay(int avisOBOrderId) {
            OrderPayLog log = new OrderPayLog();
            log.AvisOBOrderId = avisOBOrderId;
            log.PayType = "ALIPAY";
            log.Status = "WAITPAY";
            log.CreateUser = "avis";
            _orderPayLogManager.SavePayLog(log);

            OrderPayTrans trans = new OrderPayTrans();
            trans.AvisOBOrderId = avisOBOrderId;
            trans.PayType = "ALIPAY";
            trans.Status = "WAITPAY";
            trans.CreateUser = "avis";
            _orderPayTransManager.Save(trans);
        }

        private void saveCbPay(int avisOBOrderId,string out_trade_no,string trade_no,string trade_status,string notify)
        {
            OrderPayLog log = new OrderPayLog();
            log.AvisOBOrderId = avisOBOrderId;
            log.PayType = "ALIPAY";
            if (trade_status == "TRADE_SUCCESS")//支付成功
            {
                log.Status = "PAYSUCCESS";
            }
            log.CreateUser = "avis";
            _orderPayLogManager.SavePayLog(log);

            PayGatewayLog pgLog = new PayGatewayLog();
            pgLog.AvisOBOrderId = avisOBOrderId;
            pgLog.Notify = notify;
            _payGatewayLogManager.Save(pgLog);
        }
    }
}